package top.zlcode.file.service.impl;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import top.zlcode.api.file.vo.FileDeleteVO;
import top.zlcode.api.file.vo.FileUploadVO;
import top.zlcode.file.common.FileStoreConstants;
import top.zlcode.file.domain.dto.FileOperationDTO;
import top.zlcode.common.core.domain.R;
import top.zlcode.common.core.enums.ResultCode;
import top.zlcode.common.security.exception.ServiceException;
import top.zlcode.file.service.IFileService;

import java.io.File;
import java.io.IOException;
import java.util.Objects;
import java.util.UUID;

@Service
@Slf4j
public class FileServiceImpl implements IFileService {

    @Autowired
    @Qualifier("localServerIp") // 若有多个同类型Bean，通过Bean名称指定（可选，此处唯一可省略）
    private String localServerIp;

    @Value("${server.port}")
    private String serverPort;

    @Value("${file.server.agreement:http}")
    private String agreement;

    @Value("${file.config.useDomainName:false}")
    private boolean useDomainName;

    @Value("${file.config.domainName:www.zlcode.top}")
    private String domainName;


    @Override
    public R<FileUploadVO> upload(FileOperationDTO fileOperationDTO) {
        try {

            if (Objects.requireNonNull(fileOperationDTO.getFile().getOriginalFilename()).contains(FileStoreConstants.SPLIT)) {
                throw new ServiceException(ResultCode.FILE_NAME_ERROR);
            }

            // 获取文件和目标路径
            MultipartFile file = fileOperationDTO.getFile();
            String url = getFileUrl(fileOperationDTO);
            File targetFile = new File(url);

            // 确保父目录存在（这是文件写入的必要前提，不属于额外操作）
            File parentDir = targetFile.getParentFile();
            if (parentDir != null && !parentDir.exists()) {
                parentDir.mkdirs();
            }

            // 将文件写入指定路径
            file.transferTo(targetFile);
            return R.ok(buildFileUploadVO(fileOperationDTO));
        } catch (IOException e) {
            log.error("文件上传失败, 异常信息: ", e);
            throw new ServiceException(ResultCode.FILE_CREATE_FAILED);
        }
    }

    @Override
    public R<FileDeleteVO> delete(String wholeFileName) {
        String del = getFileUrlByWholeFileName(wholeFileName);
        File targetFile = new File(del);
        boolean isDelete = true;
        if (targetFile.exists()) {
            isDelete = targetFile.delete();
        } else {
            log.error("文件: {}, 不存在, 无法删除.", del);
        }
        return R.ok(FileDeleteVO.builder().wholeFileName(wholeFileName).deleted(isDelete).build());
    }

    @Override
    public R<String> getRemoteUrl(String wholeFileName) {
        String newName = wholeFileName.replace(FileStoreConstants.SPLIT, "/");
        return R.ok(getUrlPrefix() + newName);
    }

    private String getFileUrl(FileOperationDTO fileOperationDTO) {
        String newFileName = "";
        if (StrUtil.isBlank(fileOperationDTO.getFileName()))  {
            newFileName = getNewFileName(fileOperationDTO);
            fileOperationDTO.setFileName(newFileName);
        }
        return getBaseUrl(fileOperationDTO);
    }

    private String getNewFileName(FileOperationDTO fileOperationDTO) {
        String newFileName = UUID.randomUUID().toString().replace("-", "");
        int lastIndexOfDot = fileOperationDTO.getFile().getOriginalFilename().lastIndexOf('.');
        if (lastIndexOfDot > 0) {
            newFileName += fileOperationDTO.getFile().getOriginalFilename().substring(lastIndexOfDot);
        }
        return newFileName;
    }

    private String getBaseUrl(FileOperationDTO fileOperationDTO) {
        return
                System.getProperty("user.dir") + File.separator +
                        "file" + File.separator +
                        fileOperationDTO.getBucketName() + File.separator +
                        fileOperationDTO.getEndpoint() + File.separator +
                        fileOperationDTO.getFileName();
    }

    /**
     * 通过完整文件名获取这个文件在服务器上的路径
     */
    private String getFileUrlByWholeFileName(String wholeFileName) {
        String[] split = wholeFileName.split(FileStoreConstants.SPLIT);
        return
                System.getProperty("user.dir") + File.separator +
                        "file" + File.separator +
                        split[0] + File.separator +
                        split[1] + File.separator +
                        split[2];
    }

    /**
     * 构造上传图片成功响应实体
     */
    private FileUploadVO buildFileUploadVO(FileOperationDTO fileOperationDTO) {
        return FileUploadVO.builder()
                .fileName(fileOperationDTO.getFileName())
                .ip(localServerIp)
                .port(serverPort)
                .agreement(agreement)
                .wholeFileName(getWholeFileName(fileOperationDTO))
                .remoteFileUrl(getRemoteFileUrl(fileOperationDTO))
                .build();
    }

    /**
     * 获取远程地址 url 前缀
     */
    private String getUrlPrefix() {
        String pre = agreement + "://";
        if (useDomainName) {
            pre = pre + domainName;
        } else {
            pre = pre + localServerIp;
        }
        return pre + ":" + serverPort + "/file/";
    }

    /**
     * 获取文件的远程地址
     */
    private String getRemoteFileUrl(FileOperationDTO fileOperationDTO) {

        return getUrlPrefix() +
                fileOperationDTO.getBucketName() + "/" +
                fileOperationDTO.getEndpoint() + "/" +
                fileOperationDTO.getFileName();
    }

    private String getWholeFileName(FileOperationDTO fileOperationDTO) {
        return fileOperationDTO.getBucketName() + FileStoreConstants.SPLIT +
                fileOperationDTO.getEndpoint() + FileStoreConstants.SPLIT +
                fileOperationDTO.getFileName();
    }

}
